/*
 * MesoscopicTrafficSimulation.cpp
 *
 *  Created on: 12/10/2011
 *      Author: godinho
 */

#include "../../includes/evolutive/impl/MesoscopicTrafficSimulation.h"
#include <Network.h>
#include <SimulationNode.h>
#include <NodeSource.h>
#include <Controller.h>
#include <localview/Phase.h>
#include <localview/Link.h>
#include <vector>
#include <math.h>
#include <defaults.h>

typedef MesoscopicTrafficSimulation::SimulationInterfaceImpl simulationInterfaceImpl;

MesoscopicTrafficSimulation::MesoscopicTrafficSimulation() {
	mSimulationInterface = new SimulationInterfaceImpl();
}

MesoscopicTrafficSimulation::~MesoscopicTrafficSimulation() {
	delete mSimulationInterface;
}

void MesoscopicTrafficSimulation::simulate(std::vector<Case*> cases, LocalView* lv) {

	if(mControler) {
		delete mControler;
	}

	Network* net = buildSimulationEnvirionment(lv);
	mControler = new Controller(net);
	mControler->setOutput(mSimulationInterface);
	mControler->startSimulation();
}

void MesoscopicTrafficSimulation::stopSimulation() {
	mControler->stopSimulation();
	mControler = 0;
}

Network* MesoscopicTrafficSimulation::buildSimulationEnvirionment(LocalView* lv) {

	Network* network = new Network();

	Node* node;
	Node* neighborNode;
	std::vector<Node*>::iterator curNode;
	std::vector<Node*> enqueuedNode;
	std::vector<Node*> neighbors;
	std::vector<Node*>::iterator neighborsIt;
	lv->initTraversal();

	node = lv->getNetwork();
	enqueuedNode.push_back(node);
	network->addNode(node->getNodeId(), node->getX(), node->getY());
	node->setTraversalStatus(1); //Status: enqueued

	while(!enqueuedNode.empty()) {
		curNode = enqueuedNode.begin();
		node = (*curNode);
		node->setTraversalStatus(2); //Status: visited
		neighbors = node->getNeighbors();

		for(neighborsIt = neighbors.begin(); neighborsIt != neighbors.end(); neighborsIt++) {
			neighborNode = (*neighborsIt);

			if(neighborNode->getTraversalStatus() == 0) {
				network->addNode(neighborNode->getNodeId(), neighborNode->getX(), neighborNode->getY());
				network->addEdge(node->getNodeId(), neighborNode->getNodeId(), calculateTravelTime(node, neighborNode));
				neighborNode->setTraversalStatus(1); //Status: enqueued
				enqueuedNode.push_back(neighborNode);
			}
		}

		enqueuedNode.erase(curNode);
	}

	return network;
}

void MesoscopicTrafficSimulation::buildPhases(Node* n, Network* net) {

	std::vector<std::string> targets;
	std::vector<int> flushs;
	std::vector<Phase*> phases = n->getPhases();
	std::vector<Phase*>::iterator phasesIt;

	Street* toStreet;
	Phase* curPhase;
	Link* curLink;
	std::vector<Link*> links;
	std::vector<Link*>::iterator linksIt;

	for(phasesIt = phases.begin(); phasesIt != phases.end(); phasesIt++) {

		curPhase = (*phasesIt);

		links = curPhase->getLinks();

		for(linksIt = links.begin(); linksIt != links.end(); linksIt++) {
			curLink = (*linksIt);
			toStreet = curLink->getTo();
//			targests.push_back(toStreet->);
		}

		targets.clear();
		flushs.clear();
	}


}

int MesoscopicTrafficSimulation::calculateTravelTime(Node* n1, Node* n2) {

	double distance = sqrt(pow(n1->getX()-n2->getX(), 2) + pow(n1->getY()-n2->getY(), 2));

	return (int) (distance / ((float) MEAN_SEED * 1000));
}

simulationInterfaceImpl::SimulationInterfaceImpl() {

}

simulationInterfaceImpl::~SimulationInterfaceImpl() {

}

void simulationInterfaceImpl::startStep(int step, Network* network) {

}

void simulationInterfaceImpl::endStep(int step, Network* network) {

}

void simulationInterfaceImpl::startSimulation(Network* network) {

}

void simulationInterfaceImpl::endSimulation(Network* network) {

}
